﻿#region zh-CHS 2006 - 2010 DemoSoft 团队 | en 2006-2010 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2010 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demo.Mmose.Core.Common;
using Demo.Mmose.Core.Entity.Creature;
using Demo.Mmose.Core.Timer;
using Demo.Mmose.Core.Common.Atom;
using System.Threading;
using Demo.Mmose.Core.Util;
#endregion

namespace Demo.Mmose.Core.Entity.Suit.Spell
{

    /// <summary>
    /// 技能光环
    /// </summary>
    public class Aura
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        public Aura()
        {

        }

        /// <summary>
        /// 
        /// </summary>
        public Aura( long serial )
        {
            m_Serial = serial;
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS Serial属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Serial m_Serial = 0;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public Serial Serial
        {
            get { return m_Serial; }
            set { m_Serial = value; }
        }

        #endregion

        #region zh-CHS Owner属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Unit m_Owner = null;
        #endregion
        /// <summary>
        /// 拥有者的对象
        /// </summary>
        public Unit Owner
        {
            get { return m_Owner; }
            internal set { m_Owner = value; }
        }

        #endregion

        #region zh-CHS Caster属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Unit m_Caster = null;
        #endregion
        /// <summary>
        /// 施法者的对象
        /// </summary>
        public Unit Caster
        {
            get { return m_Caster; }
            set { m_Caster = value; }
        }

        #endregion

        #region zh-CHS DelayTime属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private TimeSpan m_DelayTime = TimeSpan.Zero;
        #endregion
        /// <summary>
        /// 时间延迟
        /// </summary>
        public TimeSpan DelayTime
        {
            get
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    m_DelayTime = timeSlice.DelayTime;

                return m_DelayTime;
            }
            set
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    timeSlice.DelayTime = value;

                m_DelayTime = value;
            }
        }

        #endregion

        #region zh-CHS IntervalTime属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private TimeSpan m_Interval = TimeSpan.Zero;
        #endregion
        /// <summary>
        /// 时间间隔
        /// </summary>
        public TimeSpan IntervalTime
        {
            get
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    m_Interval = timeSlice.IntervalTime;

                return m_Interval;
            }
            set
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    timeSlice.IntervalTime = value;

                m_Interval = value;
            }
        }

        #endregion

        #region zh-CHS TimeLeft属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 剩余时间
        /// </summary>
        private TimeSpan m_TimeLeft = TimeSpan.Zero;
        #endregion
        /// <summary>
        /// 剩余时间
        /// </summary>
        public TimeSpan TimeLeft
        {
            get
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    m_TimeLeft = timeSlice.TimeLeft;

                return m_TimeLeft;
            }
            set
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    timeSlice.TimeLeft = value;

                m_TimeLeft = value;
            }
        }

        #endregion

        #region zh-CHS Times属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_Times = 0;
        #endregion
        /// <summary>
        /// 使用次数
        /// </summary>
        public long Times
        {
            get
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    m_Times = timeSlice.Times;

                return m_Times;
            }
            set
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                    timeSlice.Times = value;

                m_Times = value;
            }
        }

        #endregion

        #region zh-CHS IsAllowReplace属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private bool m_IsAllowReplace = true;
        #endregion
        /// <summary>
        /// 是否可以替换
        /// </summary>
        public bool IsAllowReplace
        {
            get { return m_IsAllowReplace; }
            set { m_IsAllowReplace = value; }
        }

        #endregion

        #region zh-CHS IsAllowRemove属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private bool m_IsAllowRemove = true;
        #endregion
        /// <summary>
        /// 是否可以移除
        /// </summary>
        public bool IsAllowRemove
        {
            get { return m_IsAllowRemove; }
            set { m_IsAllowRemove = value; }
        }

        #endregion

        #region zh-CHS IsHideAura属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private bool m_IsHideAura = false;
        #endregion
        /// <summary>
        /// 是否可以隐藏
        /// </summary>
        public bool IsHideAura
        {
            get { return m_IsHideAura; }
            set { m_IsHideAura = value; }
        }

        #endregion

        #region zh-CHS AuraPriority属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private AuraPriority m_AuraPriority = AuraPriority.Normal;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public AuraPriority AuraPriority
        {
            get { return m_AuraPriority; }
            set { m_AuraPriority = value; }
        }

        #endregion

        #region zh-CHS AuraEffect属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private AuraEffect m_AuraEffect = AuraEffect.None;
        #endregion
        /// <summary>
        /// 技能光环效果
        /// </summary>
        public AuraEffect AuraEffect
        {
            get { return m_AuraEffect; }
            set { m_AuraEffect = value; }
        }

        #endregion

        #region zh-CHS AuraCollection属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private AuraCollection m_Parent = null;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public AuraCollection Parent
        {
            get { return m_Parent; }
            internal set { m_Parent = value; }
        }
        #endregion

        #region zh-CHS Running属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private LockCheck m_Running = new LockCheck( false );
        #endregion
        /// <summary>
        /// 是否已经运行过
        /// </summary>
        public bool Running
        {
            get { return m_Running.IsValid(); }
        }

        #endregion

        #endregion

        #region zh-CHS 内部保护属性 | en Protected Internal Properties

        #region zh-CHS AuraHandler属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private IAuraHandler m_AuraHandler = null;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        internal IAuraHandler AuraHandler
        {
            get { return m_AuraHandler; }
            set { m_AuraHandler = value; }
        }

        #endregion

        #endregion

        #region zh-CHS 共有方法 | en Public Methods

        /// <summary>
        /// 调用（同步）
        /// </summary>
        public void Action( object arg )
        {
            this.AuraActionCallback( arg );
        }

        /// <summary>
        /// 调用（异步）
        /// </summary>
        public void AsyncAction( object arg )
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 技能光环回调
        /// </summary>
        private void AuraActionCallback( object arg )
        {
            // 技能光环的回调事件
            EventHandler<AuraActionCallEventArgs> tempActionCallEventArgs = m_EventActionCallback;
            if ( tempActionCallEventArgs != null )
            {
                AuraActionCallEventArgs eventArgs = new AuraActionCallEventArgs( this, arg );

                tempActionCallEventArgs( this, eventArgs );
            }
        }

        #endregion

        #region zh-CHS 内部保护方法 | en Protected Internal Methods

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private TimeSlice m_AuraTimeSlice = null;
        #endregion
        /// <summary>
        /// 开始技能光环
        /// </summary>
        internal void Start()
        {
            IAuraHandler auraHandler = m_AuraHandler;
            if ( auraHandler == null )
                return;

            if ( m_Running.SetValid() == true ) // 是否初始化成功
            {
                auraHandler.Initialize( this );

                // 因为已经检测过了，所以检查是线程安全的
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                {
                    timeSlice.Stop();
                    timeSlice = null;
                }

                timeSlice = new DelayCallTimer( TimerPriority.Normal, m_DelayTime, m_Interval, m_Times, m_TimeLeft, this.AuraTimeSliceCallback );
                timeSlice.StopTimeSlice += new EventHandler<StopTimeSliceEventArgs>( this.AuraStopTimeSlice );

                // 设置值
                m_AuraTimeSlice = timeSlice;

                // 开始
                timeSlice.Start();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        private void AuraStopTimeSlice( object sender, StopTimeSliceEventArgs eventArgs )
        {
            AuraCollection auraCollection = m_Parent;
            if ( auraCollection == null )
                auraCollection.RemoveAura( this.Serial );
        }

        /// <summary>
        /// 技能光环回调
        /// </summary>
        private void AuraTimeSliceCallback()
        {
            IAuraHandler auraHandler = m_AuraHandler;
            if ( auraHandler == null )
                return;

            // 检查目标是否有效
            if ( auraHandler.CheckValidTarget( this ) == true )
            {
                // 技能光环回调的开始事件
                EventHandler<ApplyingAuraCallEventArgs> tempApplyingEventArgs = m_EventApplyingAura;
                if ( tempApplyingEventArgs != null )
                {
                    ApplyingAuraCallEventArgs eventArgs = new ApplyingAuraCallEventArgs( this );
                    tempApplyingEventArgs( this, eventArgs );

                    if ( eventArgs.IsCancel == true )
                        return;
                }

                auraHandler.Apply( this );

                // 技能光环回调的结束事件
                EventHandler<ApplyedAuraCallEventArgs> tempApplyedEventArgs = m_EventApplyedAura;
                if ( tempApplyedEventArgs != null )
                {
                    ApplyedAuraCallEventArgs eventArgs = new ApplyedAuraCallEventArgs( this );
                    tempApplyedEventArgs( this, eventArgs );
                }
            }
        }

        /// <summary>
        /// 停止技能光环
        /// </summary>
        internal void Stop()
        {
            if ( m_Running.SetInvalid() == true ) // 是否无效成功
            {
                TimeSlice timeSlice = m_AuraTimeSlice;
                if ( timeSlice != null )
                {
                    // 可能出错的机会在于不用线程之间来回的调用Start()和Stop()
                    m_AuraTimeSlice = null; // 因为已经检测过了，所以置空是线程安全的
                    
                    timeSlice.Stop();
                }

                // 移去
                m_AuraHandler.Remove( this );
                // 清楚
                m_AuraHandler.Cleanup( this );
            }
        }

        #endregion

        #region zh-CHS 共有事件 | en Public Event

        #region zh-CHS ApplyingAuraCallEventArgs事件 | en Public Event

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<ApplyingAuraCallEventArgs> m_EventApplyingAura;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventApplyingAura = new SpinLock();
        #endregion
        /// <summary>
        /// 执行动作之前
        /// </summary>
        public event EventHandler<ApplyingAuraCallEventArgs> ApplyingAura
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventApplyingAura );
                try
                {
                    m_EventApplyingAura += value;
                }
                finally
                {
                    m_LockEventApplyingAura.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventApplyingAura );
                try
                {
                    m_EventApplyingAura -= value;
                }
                finally
                {
                    m_LockEventApplyingAura.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<ApplyedAuraCallEventArgs> m_EventApplyedAura;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventApplyedAura = new SpinLock();
        #endregion
        /// <summary>
        /// 执行动作之后
        /// </summary>
        public event EventHandler<ApplyedAuraCallEventArgs> ApplyedAura
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventApplyedAura );
                try
                {
                    m_EventApplyedAura += value;
                }
                finally
                {
                    m_LockEventApplyedAura.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventApplyedAura );
                try
                {
                    m_EventApplyedAura -= value;
                }
                finally
                {
                    m_LockEventApplyedAura.Exit();
                }
            }
        }
        #endregion

        #region zh-CHS ActionCallback事件 | en Public Event

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<AuraActionCallEventArgs> m_EventActionCallback;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventActionCallback = new SpinLock();
        #endregion
        /// <summary>
        /// 添加回调事件
        /// </summary>
        public event EventHandler<AuraActionCallEventArgs> ActionCallback
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventActionCallback );
                try
                {
                    m_EventActionCallback += value;
                }
                finally
                {
                    m_LockEventActionCallback.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventActionCallback );
                try
                {
                    m_EventActionCallback -= value;
                }
                finally
                {
                    m_LockEventActionCallback.Exit();
                }
            }
        }
        #endregion

        #endregion
    }

}
#endregion
